using System.Collections.Generic;
using Castle.ActiveRecord;

namespace Scrummer.Models
{
	[ActiveRecord(
		DiscriminatorColumn = "type",
		DiscriminatorType = "String",
		DiscriminatorValue = "workitem")]
	public abstract class WorkItem : AbstractModel<WorkItem>
	{
		private string name;
		private Backlog backlog;
		private Priority priority = Priority.Blank;
		private double detailEstimate;
		private IList<WorkItem> children;
		private Status status = Status.Blank;
		private double effortRemaining;
		private double effort;
		private int estimate;
		private string notes;
		private WorkItem parent;

		[Property]
		public string Name
		{
			get { return name; }
			set { name = value; }
		}

		[Property]
		public string PriorityString
		{
			get { return priority.Name; }
			protected set { priority = Priority.Decode(value); }
		}

		public Priority Priority
		{
			get { return priority; }
			set { priority = value; }
		}

		[BelongsTo]
		public Backlog Backlog
		{
			get { return backlog; }
			set{backlog = value;}
		}

		[BelongsTo]
		public WorkItem Parent
		{
			get { return parent; }
			set { parent = value; }
		}

		[HasMany(Cascade = ManyRelationCascadeEnum.AllDeleteOrphan)]
		public IList<WorkItem> Children
		{
			get
			{
				if (children == null)
					children = new List<WorkItem>();

				return children;
			}
			protected set { children = value; }
		}

		[Property]
		public virtual double DetailEstimate
		{
			get
			{
				if(EstimatesEditable)
					return detailEstimate;
				else
				{
					double sum = 0;
					foreach (WorkItem child in Children)
						sum += child.DetailEstimate;
					return sum;
				}
			}
			set{detailEstimate = value;}
		}

		public bool EstimatesEditable
		{
			get { return Children.Count == 0; }
		}

		[Property]
		public string StatusString
		{
			get { return status.Name; }
			protected set { status = Status.Decode(value); }
		}

		public Status Status
		{
			get { return status; }
			set { status = value; }
		}

		[Property]
		public double EffortRemaining
		{
			get
			{
				if(EstimatesEditable)
					return effortRemaining;
				else
				{
					double sum = 0;
					foreach (WorkItem child in Children)
						sum += child.EffortRemaining;
					return sum;
				}
			}
			set{effortRemaining = value;}
		}

		[Property]
		public double Effort
		{
			get
			{
				if(EstimatesEditable)
					return effort;
				else
				{
					double sum = 0;
					foreach (WorkItem child in Children)
						sum += child.Effort;
					return sum;
				}
			}
			set{effort = value;}
		}

		[Property]
		public int Estimate
		{
			get { return estimate; }
			set { estimate = value; }
		}

		[Property]
		public string Notes
		{
			get { return notes; }
			set { notes = value; }
		}

		public static IList<WorkItem> FindAll(int projectId)
		{
			return Project.Find(projectId).Backlog.WorkItems;
		}
	}
}
